package org.ewancle.springboothivehdfs.controller;

import lombok.extern.slf4j.Slf4j;
import org.apache.hadoop.fs.FileStatus;
import org.ewancle.springboothivehdfs.service.HDFSService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

@Slf4j
@RestController
@RequestMapping("/api/hdfs")
public class HDFSController {

    private final HDFSService hdfsService;

    @Autowired
    public HDFSController(HDFSService hdfsService) {
        this.hdfsService = hdfsService;
    }

    @PostMapping("/mkdir")
    public ResponseEntity<Map<String, Object>> mkdir(@RequestParam String path) {
        Map<String, Object> response = new HashMap<>();
        boolean result = hdfsService.mkdir(path);
        response.put("success", result);
        response.put("path", path);

        return new ResponseEntity<>(response, result ? HttpStatus.OK : HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @PostMapping("/upload")
    public ResponseEntity<Map<String, Object>> uploadFile(
            @RequestParam("file") MultipartFile file,
            @RequestParam("path") String path) {

        Map<String, Object> response = new HashMap<>();
        String destPath = path;

        // 如果路径是目录，则使用原始文件名
        if (path.endsWith("/")) {
            destPath = path + file.getOriginalFilename();
        }

        boolean result = hdfsService.uploadFile(file, destPath);
        response.put("success", result);
        response.put("path", destPath);
        response.put("size", file.getSize());

        return new ResponseEntity<>(response, result ? HttpStatus.OK : HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @PostMapping("/upload-async")
    public CompletableFuture<ResponseEntity<Map<String, Object>>> uploadFileAsync(
            @RequestParam("file") MultipartFile file,
            @RequestParam("path") String path) {

        String destPath = path;

        // 如果路径是目录，则使用原始文件名
        if (path.endsWith("/")) {
            destPath = path + file.getOriginalFilename();
        }

        final String finalDestPath = destPath;

        return hdfsService.uploadFileAsync(file, destPath)
                .thenApply(result -> {
                    Map<String, Object> response = new HashMap<>();
                    response.put("success", result);
                    response.put("path", finalDestPath);
                    response.put("size", file.getSize());

                    return new ResponseEntity<>(response,
                            result ? HttpStatus.OK : HttpStatus.INTERNAL_SERVER_ERROR);
                });
    }

    @GetMapping("/list")
    public ResponseEntity<?> listFiles(@RequestParam String path) {
        try {
            List<FileStatus> statusList = hdfsService.listFiles(path);
            List<Map<String, Object>> resultList = new ArrayList<>();

            for (FileStatus status : statusList) {
                Map<String, Object> fileInfo = new HashMap<>();
                fileInfo.put("path", status.getPath().toString());
                fileInfo.put("name", status.getPath().getName());
                fileInfo.put("isDirectory", status.isDirectory());
                fileInfo.put("length", status.getLen());
                fileInfo.put("modificationTime", status.getModificationTime());
                fileInfo.put("permission", status.getPermission().toString());
                fileInfo.put("owner", status.getOwner());
                fileInfo.put("group", status.getGroup());

                resultList.add(fileInfo);
            }

            return ResponseEntity.ok(resultList);
        } catch (IOException e) {
            log.error("List files failed: {}", path, e);
            Map<String, Object> error = new HashMap<>();
            error.put("error", e.getMessage());
            return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @GetMapping("/read")
    public ResponseEntity<?> readFile(@RequestParam String path) {
        try {
            String content = hdfsService.readFile(path);
            Map<String, Object> response = new HashMap<>();
            response.put("path", path);
            response.put("content", content);

            return ResponseEntity.ok(response);
        } catch (IOException e) {
            log.error("Read file failed: {}", path, e);
            Map<String, Object> error = new HashMap<>();
            error.put("error", e.getMessage());
            return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @DeleteMapping("/delete")
    public ResponseEntity<Map<String, Object>> delete(
            @RequestParam String path,
            @RequestParam(defaultValue = "false") boolean recursive) {

        Map<String, Object> response = new HashMap<>();
        boolean result = hdfsService.delete(path, recursive);
        response.put("success", result);
        response.put("path", path);

        return new ResponseEntity<>(response, result ? HttpStatus.OK : HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @PostMapping("/rename")
    public ResponseEntity<Map<String, Object>> rename(
            @RequestParam String src,
            @RequestParam String dest) {

        Map<String, Object> response = new HashMap<>();
        boolean result = hdfsService.rename(src, dest);
        response.put("success", result);
        response.put("source", src);
        response.put("destination", dest);

        return new ResponseEntity<>(response, result ? HttpStatus.OK : HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @GetMapping("/exists")
    public ResponseEntity<Map<String, Object>> exists(@RequestParam String path) {
        Map<String, Object> response = new HashMap<>();
        boolean result = hdfsService.exists(path);
        response.put("exists", result);
        response.put("path", path);

        return ResponseEntity.ok(response);
    }
}

